export {}
interface Animal {
	name:string;
	age:number
}
interface Person {
	name:string;
	age:number;
	gender:number
}
function getName(a:Animal):string{
	return a.name
}
let a:Animal = {
	name:'cat',
	age:10
}
getName(a)
let p:Person = {
	name:"june",
	age:20,
	gender:0
}
getName(p)

//基本数据类型的兼容性
let num:string | number;
let str:string = 'jinyq'
num = str

let num2:{
	toString():string
}
let str2:string = 'jack'
num2 = str2
// str2= num2

//类的兼容性
namespace aa{
	class Animal{
		name!:string
	}
	class Bird extends Animal{
		age!:number
	}
	let a:Animal;
	let b:Bird;
	a = b;
	//b =a
}

// 函数的兼容性
// 比较参数 比较返回值
type Func = (a:number,b:number) => void
let sum :Func;
function f1(a:number,b:number):void{}
sum = f1
// 参数少一个可以
function f2(a:number):void{}
sum = f2
// 少两个参数也可以
function f3():void{}
sum = f3
//多一个不行
function f4(a:number,b:number,c:number):void{}
sum = f4


//比较返回值
type  GetPerson= ()=>{name:string,age:number}
let getPerson:GetPerson;
function g1(){
	return {name:'jinyq',age:20}
}
getPerson = g1

// 多一个可以
function g2(){
	return {name:'jinyq',age:20,gender:0}
}
getPerson = g2

//少一个不行
function g3(){
	return {name:'jinyq'}
}
getPerson = g3

// 一切的一切是
/**
 * 函数的协变与逆变
协变（Covariant）：只在同一个方向；
逆变（Contravariant）：只在相反的方向；
双向协变（Bivariant）：包括同一个方向和不同方向；
不变（Invariant）：如果类型不完全相同，则它们是不兼容的。

A ≼ B 意味着 A 是 B 的子类型。

A → B 指的是以 A 为参数类型，以 B 为返回值类型的函数类型。
x : A 意味着 x 的类型为 A

返回值类型是协变的，而参数类型是逆变的
返回值类型可以传子类,参数可以传父类
参数逆变父类 返回值协变子类 搀你父,返鞋子
 */

class Animal{

}
class Dog extends Animal{
	public name:string = 'Dog'
}
class BlackDog extends Dog{
	public age:number = 10
}
class WhiteDog extends Dog{
	public home:string = '北京'
}
let animal:Animal;
let dog: Dog;
let blackDog: BlackDog;
let whiteDog: WhiteDog;
type Callback =(dog:Dog)=>Dog;
function exec(callback:Callback):void{}
/**
 * 参数可以传自己和自己的父类
 * 返回值可以传自己和自己的子类
 * 四种情况
 * 1.参数传子类返回值子类  n
 * 2.参数是子类返回值是父类 n
 * 3.参数是父类返回值是父类 n
 * 4.参数是父类返回值是子类 y
 */
type ChildToChild = (blackDog:BlackDog) =>BlackDog
let childToChild:ChildToChild
exec(childToChild)
type ChildToFather = (blackDog:BlackDog) =>Animal
let childToFather:ChildToFather
exec(childToFather)
type FatherToFather = (animal:Animal) => Animal
let fatherToFather:FatherToFather
exec(fatherToFather)
type FatherToChild = (animal:Animal) =>BlackDog
let fatherToChild:FatherToChild
exec(fatherToChild)